package com.minimalist.lindi.manager;

import com.minimalist.common.entity.lindi.enums.TownEnum;
import com.minimalist.common.entity.lindi.po.*;
import com.minimalist.lindi.mapper.*;
import com.mybatisflex.core.query.QueryWrapper;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import java.math.BigDecimal;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.*;
import java.util.stream.Collectors;

/**
 * 仪表板数据处理器
 * 提供林地指标交易平台仪表板所需的各种统计数据
 *
 * @author 11987
 */
@Component
public class DashboardManager{
    private static final Logger log = LoggerFactory.getLogger(DashboardManager.class);


    @Autowired
    private LindiEnterpriseRegistrationMapper enterpriseRegistrationMapper;

    @Autowired
    private LindiSubsidyApplicationMapper subsidyApplicationMapper;

    @Autowired
    private LindiTradeApplicationMapper tradeApplicationMapper;

    @Autowired
    private LindiIndexMapper indexMapper;

    @Autowired
    private LindiPurchaseIndexRecordMapper purchaseIndexRecordMapper;

    @Autowired
    private LindiPurchaseTownIndexMapper purchaseTownIndexMapper;

    @Autowired
    private LindiIndexChangeRecordMapper indexChangeRecordMapper;

    /**
     * 获取平台统计概览数据
     *
     * @return 平台概览统计
     */
    public Map<String, Object> getPlatformOverview(){
        Map<String, Object> overview = new HashMap<>();

        try{
            // 统计总交易金额（只统计已完成的交易申请）
            List<LindiTradeApplication> tradeApplications = tradeApplicationMapper.selectAll();
            BigDecimal totalAmount = tradeApplications.stream()
                    .filter(trade -> trade.getMoney() != null
                            && !trade.getMoney().isEmpty()
                            && trade.getTradeStatus() != null
                            && trade.getTradeStatus() == 2) // 只统计已完成的交易
                    .map(trade -> {
                        try{
                            return new BigDecimal(trade.getMoney());
                        } catch (NumberFormatException e){
                            return BigDecimal.ZERO;
                        }
                    })
                    .reduce(BigDecimal.ZERO, BigDecimal::add);

            // 统计总订单数（只统计已完成的交易申请）
            long totalOrders = tradeApplications.stream()
                    .filter(trade -> trade.getTradeStatus() != null && trade.getTradeStatus() == 2)
                    .count();

            // 统计总企业数
            long totalCompanies = enterpriseRegistrationMapper.selectCountByQuery(
                    QueryWrapper.create());

            // 统计总林地面积（从镇街购买指标表获取）
            List<LindiPurchaseTownIndex> purchaseTownIndexes = purchaseTownIndexMapper.selectAll();
            BigDecimal totalArea = purchaseTownIndexes.stream()
                    .filter(record -> record.getTownIndex() != null && !record.getTownIndex().isEmpty())
                    .map(record -> {
                        try{
                            return new BigDecimal(record.getTownIndex());
                        } catch (NumberFormatException e){
                            return BigDecimal.ZERO;
                        }
                    })
                    .reduce(BigDecimal.ZERO, BigDecimal::add);

            overview.put("totalAmount", formatNumber(totalAmount.doubleValue()));
            overview.put("totalOrders", String.valueOf(totalOrders));
            overview.put("totalCompanies", String.valueOf(totalCompanies));
            overview.put("totalArea", formatNumber(totalArea.doubleValue()));

        } catch (Exception e){
            log.error("获取平台概览数据失败", e);
            // 返回默认值
            overview.put("totalAmount", "0.0");
            overview.put("totalOrders", "0");
            overview.put("totalCompanies", "0");
            overview.put("totalArea", "0.0");
        }

        return overview;
    }

    /**
     * 获取各街道镇区林地面积统计数据
     *
     * @return 面积统计列表
     */
    public List<Map<String, Object>> getAreaStatistics(){
        List<Map<String, Object>> result = new ArrayList<>();

        try{
            // 从镇街购买指标表中统计各街道镇区的购买面积
            List<LindiPurchaseTownIndex> purchaseTownIndexes = purchaseTownIndexMapper
                    .selectAll();

            // 按镇街名称分组统计购买面积
            Map<String, Double> areaByTown = purchaseTownIndexes.stream()
                    .filter(record -> record.getTownName() != null && !record.getTownName().isEmpty())
                    .filter(record -> record.getTownIndex() != null && !record.getTownIndex().isEmpty())
                    .collect(Collectors.groupingBy(
                            LindiPurchaseTownIndex::getTownName,
                            Collectors.summingDouble(record -> {
                                try{
                                    return Double.parseDouble(record.getTownIndex());
                                } catch (NumberFormatException e){
                                    log.warn("解析购买面积失败: {}", record.getTownIndex());
                                    return 0.0;
                                }
                            })
                    ));

            // 遍历所有镇街枚举，确保每个镇街都有数据
            for (TownEnum townEnum : TownEnum.values()){
                // 跳过未知镇街

                Map<String, Object> item = new HashMap<>();
                item.put("name", townEnum.getDesc());
                // 获取该镇街的购买面积，如果没有则为0
                Double area = areaByTown.getOrDefault(townEnum.getDesc(), 0.0);
                item.put("value", String.valueOf(area.doubleValue()));
                result.add(item);
            }

        } catch (Exception e){
            log.error("获取面积统计数据失败", e);
        }

        return result;
    }

    /**
     * 获取各镇区街道林地交易情况统计
     *
     * @return 交易统计列表
     */
    public List<Map<String, Object>> getTradeStatistics(){
        List<Map<String, Object>> result = new ArrayList<>();

        try{
            // 从镇街购买指标表中获取各镇街的总面积信息
            List<LindiPurchaseTownIndex> purchaseTownIndexes = purchaseTownIndexMapper.selectAll();

            // 按镇街名称分组统计总面积
            Map<String, Double> totalAreaByTown = purchaseTownIndexes.stream()
                    .filter(record -> record.getTownName() != null && !record.getTownName().isEmpty())
                    .filter(record -> record.getTownIndex() != null && !record.getTownIndex().isEmpty())
                    .collect(Collectors.groupingBy(
                            LindiPurchaseTownIndex::getTownName,
                            Collectors.summingDouble(record -> {
                                try{
                                    return Double.parseDouble(record.getTownIndex());
                                } catch (NumberFormatException e){
                                    log.warn("解析购买面积失败: {}", record.getTownIndex());
                                    return 0.0;
                                }
                            })
                    ));

            // 从指标变更记录表中获取各镇街的已交易面积
            List<LindiIndexChangeRecord> changeRecords = indexChangeRecordMapper.selectAll();
            Map<String, Double> tradedAreaByTown = changeRecords.stream()
                    .filter(record -> record.getTownName() != null && !record.getTownName().isEmpty())
                    .filter(record -> record.getChangeQuantity() != null && !record.getChangeQuantity().isEmpty())
                    .collect(Collectors.groupingBy(
                            LindiIndexChangeRecord::getTownName,
                            Collectors.summingDouble(record -> {
                                try{
                                    return Double.parseDouble(record.getChangeQuantity());
                                } catch (NumberFormatException e){
                                    log.warn("解析变更面积失败: {}", record.getChangeQuantity());
                                    return 0.0;
                                }
                            })
                    ));

            // 为每个镇街生成交易统计数据
            for (Map.Entry<String, Double> entry : totalAreaByTown.entrySet()){
                String townName = entry.getKey();
                double totalArea = entry.getValue();
                double tradedArea = tradedAreaByTown.getOrDefault(townName, 0.0);
                double availableArea = Math.max(0, totalArea - tradedArea);

                Map<String, Object> item = new HashMap<>();
                item.put("name", townName);
                item.put("traded", String.valueOf((int) tradedArea));
                item.put("available", String.valueOf((int) availableArea));
                result.add(item);
            }

        } catch (Exception e){
            log.error("获取交易统计数据失败", e);
        }

        return result;
    }

    /**
     * 获取资金营收统计数据
     *
     * @return 营收统计列表
     */
    public List<Map<String, Object>> getRevenueStatistics(){
        List<Map<String, Object>> result = new ArrayList<>();

        try{
            List<LindiTradeApplication> tradeApplications = tradeApplicationMapper
                    .selectAll();

            // 按交易状态分类统计
            double receivedAmount = 0.0; // 已完成交易的金额
            double receivableAmount = 0.0; // 审核通过但未完成的金额
            double unreceivedAmount = 0.0; // 审核中或被拒绝的金额

            for (LindiTradeApplication trade : tradeApplications){
                if (trade.getMoney() != null && !trade.getMoney().isEmpty()){
                    try{
                        double amount = Double.parseDouble(trade.getMoney());

                        // 根据交易状态分类（假设状态：0-审核中，1-审核通过，2-已完成，3-被拒绝）
                        Integer status = trade.getTradeStatus();
                        if (status != null){
                            switch (status){
                                case 2: // 已完成
                                    receivedAmount += amount;
                                    break;
                                case 1: // 审核通过
                                    receivableAmount += amount;
                                    break;
                                default: // 审核中或被拒绝
                                    unreceivedAmount += amount;
                                    break;
                            }
                        }
                    } catch (NumberFormatException e){
                        log.warn("解析交易金额失败: {}", trade.getMoney());
                    }
                }
            }

            Map<String, Object> received = new HashMap<>(1);
            received.put("name", "实收");
            received.put("value", String.valueOf((int) receivedAmount));
            result.add(received);

            Map<String, Object> receivable = new HashMap<>(1);
            receivable.put("name", "应收");
            receivable.put("value", String.valueOf((int) receivableAmount));
            result.add(receivable);

            Map<String, Object> unreceived = new HashMap<>(1);
            unreceived.put("name", "未收");
            unreceived.put("value", String.valueOf((int) unreceivedAmount));
            result.add(unreceived);

        } catch (Exception e){
            log.error("获取营收统计数据失败", e);
        }

        return result;
    }

    /**
     * 获取地图数据
     *
     * @return 地图数据列表
     */
    public List<Map<String, Object>> getMapData(){
        List<Map<String, Object>> result = new ArrayList<>();

        try{
            // 从镇街购买指标表中获取各镇街的总面积信息
            List<LindiPurchaseTownIndex> purchaseTownIndexes = purchaseTownIndexMapper.selectAll();

            // 按镇街名称分组统计总面积
            Map<String, Double> totalAreaByTown = purchaseTownIndexes.stream()
                    .filter(record -> record.getTownName() != null && !record.getTownName().isEmpty())
                    .filter(record -> record.getTownIndex() != null && !record.getTownIndex().isEmpty())
                    .collect(Collectors.groupingBy(
                            LindiPurchaseTownIndex::getTownName,
                            Collectors.summingDouble(record -> {
                                try{
                                    return Double.parseDouble(record.getTownIndex());
                                } catch (NumberFormatException e){
                                    log.warn("解析购买面积失败: {}", record.getTownIndex());
                                    return 0.0;
                                }
                            })
                    ));

            // 从指标变更记录表中获取各镇街的已交易面积
            List<LindiIndexChangeRecord> changeRecords = indexChangeRecordMapper.selectAll();
            Map<String, Double> tradedAreaByTown = changeRecords.stream()
                    .filter(record -> record.getTownName() != null && !record.getTownName().isEmpty())
                    .filter(record -> record.getChangeQuantity() != null && !record.getChangeQuantity().isEmpty())
                    .collect(Collectors.groupingBy(
                            LindiIndexChangeRecord::getTownName,
                            Collectors.summingDouble(record -> {
                                try{
                                    return Double.parseDouble(record.getChangeQuantity());
                                } catch (NumberFormatException e){
                                    log.warn("解析变更面积失败: {}", record.getChangeQuantity());
                                    return 0.0;
                                }
                            })
                    ));

            // 为每个镇街生成地图数据
            for (Map.Entry<String, Double> entry : totalAreaByTown.entrySet()){
                String townName = entry.getKey();
                double totalArea = entry.getValue();
                double tradedArea = tradedAreaByTown.getOrDefault(townName, 0.0);
                double availableArea = Math.max(0, totalArea - tradedArea);

                Map<String, Object> item = new HashMap<>();
                item.put("name", townName);
                item.put("totalArea", String.valueOf((int) totalArea));
                item.put("tradedArea", String.valueOf((int) tradedArea));
                item.put("availableArea", String.valueOf((int) availableArea));
                item.put("value", String.valueOf((int) totalArea)); // 地图显示值使用总面积
                result.add(item);
            }

        } catch (Exception e){
            log.error("获取地图数据失败", e);
        }

        return result;
    }

    /**
     * 获取林地补贴申请统计数据
     *
     * @return 补贴申请统计列表
     */
    public List<Map<String, Object>> getSubsidyStatistics(){
        List<Map<String, Object>> result = new ArrayList<>();

        try{
            List<LindiSubsidyApplication> subsidyApplications = subsidyApplicationMapper.selectAll();

            // 按补贴状态分类统计
            Map<String, Long> statusCount = subsidyApplications.stream()
                    .filter(subsidy -> subsidy.getSubsidyStatus() != null)
                    .collect(Collectors.groupingBy(
                            LindiSubsidyApplication::getSubsidyStatus,
                            Collectors.counting()
                    ));

            // 审核通过
            Map<String, Object> approved = new HashMap<>(1);
            approved.put("name", "审核通过");
            approved.put("value", String.valueOf(statusCount.getOrDefault("审核通过", 0L).intValue()));
            result.add(approved);

            // 正在审核
            Map<String, Object> pending = new HashMap<>(1);
            pending.put("name", "正在审核");
            pending.put("value", String.valueOf(statusCount.getOrDefault("正在审核", 0L).intValue()));
            result.add(pending);

            // 未通过
            Map<String, Object> rejected = new HashMap<>(1);
            rejected.put("name", "未通过");
            rejected.put("value", String.valueOf(statusCount.getOrDefault("未通过", 0L).intValue()));
            result.add(rejected);

        } catch (Exception e){
            log.error("获取补贴申请统计数据失败", e);
        }

        return result;
    }

    /**
     * 获取企业信息注册统计数据
     *
     * @return 企业注册统计列表
     */
    public List<Map<String, Object>> getCompanyStatistics(){
        List<Map<String, Object>> result = new ArrayList<>();

        try{
            List<LindiEnterpriseRegistration> enterprises = enterpriseRegistrationMapper.selectAll();

            // 按状态分类统计（0-审核中，1-审核通过，2-审核未通过）
            Map<Integer, Long> statusCount = enterprises.stream()
                    .filter(enterprise -> enterprise.getStatus() != null)
                    .collect(Collectors.groupingBy(
                            LindiEnterpriseRegistration::getStatus,
                            Collectors.counting()
                    ));

            // 审核通过
            Map<String, Object> approved = new HashMap<>(1);
            approved.put("name", "审核通过");
            approved.put("value", String.valueOf(statusCount.getOrDefault(1, 0L).intValue()));
            result.add(approved);

            // 正在审核
            Map<String, Object> pending = new HashMap<>(1);
            pending.put("name", "正在审核");
            pending.put("value", String.valueOf(statusCount.getOrDefault(0, 0L).intValue()));
            result.add(pending);

            // 未通过
            Map<String, Object> rejected = new HashMap<>(1);
            rejected.put("name", "未通过");
            rejected.put("value", String.valueOf(statusCount.getOrDefault(2, 0L).intValue()));
            result.add(rejected);

        } catch (Exception e){
            log.error("获取企业注册统计数据失败", e);
        }

        return result;
    }

    /**
     * 获取交易订单统计数据（按月份）
     *
     * @return 订单统计数据
     */
    public Map<String, Object> getOrderStatistics(){
        Map<String, Object> result = new HashMap<>(12);

        try{
            List<LindiTradeApplication> tradeApplications = tradeApplicationMapper
                    .selectAll();

            // 按月份统计订单数量
            String[] months = {"1月", "2月", "3月", "4月", "5月", "6月", "7月"
                    , "8月", "9月", "10月", "11月", "12月"};
            List<String> orders = new ArrayList<>();

            for (int month = 1; month <= months.length; month++){
                // 这里应该根据实际的创建时间字段进行月份过滤
                // 暂时返回固定值，实际应用中需要根据createTime字段进行统计
                long monthlyOrders = tradeApplications.stream()
                        .filter(trade -> trade.getTradeStatus() != null && trade.getTradeStatus() == 2)
                        .count() / 12; // 简单平均分配，实际应该按月份统计
                orders.add(String.valueOf(monthlyOrders));
            }

            result.put("months", Arrays.asList(months));
            result.put("orders", orders);

        } catch (Exception e){
            log.error("获取订单统计数据失败", e);
            // 返回默认值
            result.put("months", Arrays.asList("1月", "2月", "3月", "4月", "5月", "6月"));
            result.put("orders", Arrays.asList("0", "0", "0", "0", "0", "0"));
        }

        return result;
    }

    /**
     * 生成仪表板数据
     *
     * @return 完整的仪表板数据
     */
    public Map<String, Object> generateDashboardData(){
        Map<String, Object> data = new HashMap<>();

        try{
            // 平台概览数据
            data.put("overview", getPlatformOverview());

            // 各街道镇区林地面积数据
            data.put("areaStatistics", getAreaStatistics());

            // 各镇区街道林地交易情况
            data.put("tradeStatistics", getTradeStatistics());

            // 资金营收统计
            data.put("revenueStatistics", getRevenueStatistics());

            // 地图数据
            data.put("mapData", getMapData());

            // 林地补贴申请统计
            data.put("subsidyStatistics", getSubsidyStatistics());

            // 企业注册统计
            data.put("companyStatistics", getCompanyStatistics());

            // 订单统计
            data.put("orderStatistics", getOrderStatistics());

            // 添加时间戳
            data.put("timestamp", LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")));
            data.put("updateTime", System.currentTimeMillis());

        } catch (Exception e){
            log.error("生成仪表板数据失败", e);
        }

        return data;
    }

    /**
     * 格式化数字
     *
     * @param number 数字
     * @return 格式化后的字符串
     */
    private String formatNumber(double number){
        return String.format("%.1f", number);
    }
}
